package com.pap.gateway;

import com.pap.gateway.filter.HeaderFilter;
import com.pap.gateway.filter.RequestRecordFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.http.HttpMethod;

@SpringBootApplication(exclude = {
        org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
})
public class PapGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(PapGatewayApplication.class, args);
    }

    /**
     * PAP-PS: 注意此处功能已经被替换, 详见 InitGateWayRouterConfig 类文件，将路由信息的初始化改为 从 nacos 中获取，而不是写死代码中。
     *
     * Bean 注解已经被忽略。
     * @param builder
     * @return
     */
    // @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                //basic proxy
                // 使用 eureka, 如果发现以 datas 开头的服务，则进行转发，转发至 PAP-DATAS 对应的微服务
                // 区分 GET 与 POST/PUT/DELTE 的请求，用来走不同的过滤请求
                .route ("pap-uua-put", r -> r.path ("/uua/**")
                        .and().method(HttpMethod.PUT).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-uua")
                        .order (0)
                )
                .route ("pap-uua-post", r -> r.path ("/uua/**")
                        .and().method(HttpMethod.POST).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filters(new HeaderFilter(), new RequestRecordFilter()))
                        .uri ("lb://pap-uua")
                        .order (0)
                )
                .route ("pap-uua-delete", r -> r.path ("/uua/**")
                        .and().method(HttpMethod.DELETE).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-uua")
                        .order (0)
                )
                .route ("pap-uua-get", r -> r.path ("/uua/**")
                        .and().method(HttpMethod.GET)
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-uua")
                        .order (0)
                )
                .route ("pap-rbac-put", r -> r.path ("/rbac/**")
                        .and().method(HttpMethod.PUT).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-rbac")
                        .order (0)
                )
                .route ("pap-rbac-post", r -> r.path ("/rbac/**")
                        .and().method(HttpMethod.POST).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-rbac")
                        .order (0)
                )
                .route ("pap-rbac-delete", r -> r.path ("/rbac/**")
                        .and().method(HttpMethod.DELETE).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-rbac")
                        .order (0)
                )
                .route ("pap-rbac-get", r -> r.path ("/rbac/**")
                        .and().method(HttpMethod.GET)
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-rbac")
                        .order (0)
                )
                .route ("pap-order-put", r -> r.path ("/order/**")
                        .and().method(HttpMethod.PUT).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-order")
                        .order (0)
                )
                .route ("pap-order-post", r -> r.path ("/order/**")
                        .and().method(HttpMethod.POST).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filters(new HeaderFilter(), new RequestRecordFilter()))
                        .uri ("lb://pap-order")
                        .order (0)
                )
                .route ("pap-order-delete", r -> r.path ("/order/**")
                        .and().method(HttpMethod.DELETE).and().readBody(String.class, requestBody -> {return true;})
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-order")
                        .order (0)
                )
                .route ("pap-order-get", r -> r.path ("/order/**")
                        .and().method(HttpMethod.GET)
                        .filters (f -> f
                                .filter(new RequestRecordFilter()))
                        .uri ("lb://pap-order")
                        .order (0)
                )
                // TODO 基于路由权重的断言 可以通过 weight 进行权重区分，走不通的路由， 注意 ID 设定不能相同，后面跳转到的 eureka 的地址也可以不同(lb代表从注册中心获取服务)， 走到不同的服务.
                // TODO 其实绝大部分的功能，完全可以通过服务端的接口划分进行限定，某方法的 version 版本不同，划分到不同的 服务端地址 中.
//                .route ("PAP-RBAC-GET-1", r -> r.weight("", 50).and().path ("/rbac/**")
//                        .and().method(HttpMethod.GET).filters (f -> f.filter(new RequestRecordFilter())).uri ("lb://PAP-RBAC").order (0)
//                )
//                .route ("PAP-RBAC-GET-2", r -> r.weight("", 50).and().path ("/rbac/**")
//                        .and().method(HttpMethod.GET).filters (f -> f.filter(new RequestRecordFilter())).uri ("lb://PAP-RBAC1").order (0)
//                )
                // TODO 根据请求头里面的版本信息，分发到不同的实例中。
//                .route ("PAP-RBAC-V1.0.3", r -> r.header("papVersion", "1.0.3").and().path ("/rbac/**")
//                        .and().method(HttpMethod.GET).filters (f -> f.filter(new RequestRecordFilter())).uri ("lb://PAP-RBAC")
//                        // 值越大则优先级越低。
//                        .order (0)
//                )
//                // 标准的版本号必须采用X.Y.Z的格式，且为非负的整数，且禁止在数字前方补零。 其中X为主版本号、Y是次版本号、Z为修订号。 正则表达式如下：
//                .route ("PAP-RBAC-exist", r -> r.header("papVersion", "(([0-9]|([1-9]([0-9]*))).){2}([0-9]|([1-9]([0-9]*)))").and().path ("/rbac/**")
//                        .and().method(HttpMethod.GET).filters (f -> f.filter(new RequestRecordFilter())).uri ("lb://PAP-RBAC")
//                        // 值越大则优先级越低。
//                        .order (0)
//                )
//                .route ("PAP-RBAC-noexist", r -> r.path ("/rbac/**")
//                        .and().method(HttpMethod.GET).filters (f -> f.filter(new RequestRecordFilter())).uri ("lb://PAP-RBAC")
//                        // 值越大则优先级越低。
//                        .order (0)
//                )
                .build();
    }

}
